﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using ANZ_AIM_BLL.Model;
using ANZ_AIM_GUI.Utils;
using ANZ_AIM_BLL;
using ANZ_AIM_FRAMEWORK;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Text.RegularExpressions;
using log4net;

namespace ANZ_AIM_OFFLINETOOL
{
    public partial class frmCandidateMaster : Form
    {
        //log4net
        private static readonly ILog logger = LogManager.GetLogger(typeof(frmCandidateMaster));

        private string lastPath = Application.StartupPath;

        public int OpMode { get; set; }//1:insert list employment, 2: update change info
        
        public Dictionary<string, string> Candidate_FieldLabelDict { get; set; }
        public Dictionary<string, string> Employment_FieldLabelDict { get; set; }
        public Dictionary<string, string> ChangeRequest_Employment_FieldLabelDict { get; set; }

        public EmploymentOffline employment { get; set; }//load data, save local to DB
        public EmploymentOffline employmentTemp { get; set; }//load data, change info

        public MailConfig mailConfig { get; set; }

        public List<EmploymentOffline> listEmploymentOffline = new List<EmploymentOffline>();
        public List<CandidateOffline> listCandidateOffline = new List<CandidateOffline>();

        DataTable dtDataEmployeeChangeTemp = new DataTable();

        public frmCandidateMaster()
        {
            InitializeComponent();

            try
            {
                //build label for show
                BuildCandidateOfflineLabel();
                BuildEmploymentOfflineLabel();
                BuildChangeRequestEmploymentOfflineLabel();

                //load mail config
                MailConfigBLL mailConfigBll = new MailConfigBLL();
                mailConfig = mailConfigBll.GetMailConfig();

                if (mailConfig != null)
                {
                    txtBranch.Text = mailConfig.Branch;
                    txtFloor.Text = mailConfig.Floor;
                }

                //load employment
                LoadDataEmploymentOffline();

                //load column
                dtDataEmployeeChangeTemp.Columns.Add("ProfileID");
                dtDataEmployeeChangeTemp.Columns.Add("BatchFile");
                dtDataEmployeeChangeTemp.Columns.Add("FieldChange");
                dtDataEmployeeChangeTemp.Columns.Add("OldValue");
                dtDataEmployeeChangeTemp.Columns.Add("NewValue");
                dtDataEmployeeChangeTemp.Columns.Add("FirstValue");

                EmploymentOfflineBLL eoBLL = new EmploymentOfflineBLL();
                dtDataEmployeeChangeTemp = eoBLL.GetDataChangeTemp();

                //load info change
                RefreshEmploymentChangeCount();

                //load label info
                RefreshCandidateCount();
            }
            catch (Exception ex) { throw ex; }
        }

        #region Candidate

        public void LoadData()
        {
            try
            {
                var listBinding = new BindingList<CandidateOffline>(listCandidateOffline);

                dgvDataCandidateOffline.DataSource = null;
                dgvDataCandidateOffline.Columns.Clear();
                dgvDataCandidateOffline.DataSource = listBinding;
                dgvDataCandidateOffline.AutoResizeColumns();

                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(CandidateOffline));
                foreach (PropertyDescriptor prop in properties)
                {
                    dgvDataCandidateOffline.Columns[prop.Name].HeaderText = Candidate_FieldLabelDict[prop.Name];
                    string dataType = prop.PropertyType.Name;

                    if (!dataType.ToUpper().Equals("STRING"))
                    {
                        dgvDataCandidateOffline.Columns[prop.Name].DefaultCellStyle.Format = "dd MMM, yyyy";
                    }
                }
            }
            catch (Exception ex) { throw ex; }
        }
        public void BuildCandidateOfflineLabel()
        {
            Candidate_FieldLabelDict = new Dictionary<string, string>();

            Candidate_FieldLabelDict.Add("CVCode", "CV Code"); // PersonalCode -> CVCode
            Candidate_FieldLabelDict.Add("Channel", "Channel");
            Candidate_FieldLabelDict.Add("Team", "Team");
            Candidate_FieldLabelDict.Add("FullName_E", "FullName_E");
            Candidate_FieldLabelDict.Add("FullName_V", "FullName_V");
            Candidate_FieldLabelDict.Add("CellPhone", "CellPhone");
            Candidate_FieldLabelDict.Add("DateOfBirth", "Date Of Birth");
            Candidate_FieldLabelDict.Add("College", "College");
            Candidate_FieldLabelDict.Add("Qualification", "Qualification");
            Candidate_FieldLabelDict.Add("IDNumber", "ID Number");
            Candidate_FieldLabelDict.Add("IssuedDate", "Issued Date");
            Candidate_FieldLabelDict.Add("IssuedPlace", "Issued Place");
            Candidate_FieldLabelDict.Add("PermanentAddress", "Permanent Address");
            Candidate_FieldLabelDict.Add("Interviewer", "Interviewer");
            Candidate_FieldLabelDict.Add("InterviewDate", "Interview Date");
            Candidate_FieldLabelDict.Add("TrainingCallStatus", "Training Call Status");
            Candidate_FieldLabelDict.Add("TrainingCallStatusRemarks", "Training Call Status Remarks");
            Candidate_FieldLabelDict.Add("CICSanctionDeliveryDate", "CIC Sanction Delivery Date");
            Candidate_FieldLabelDict.Add("CICSanctionDelivererName", "CIC Sanction Deliverer Name");
            Candidate_FieldLabelDict.Add("CICResult", "CIC Result");
            Candidate_FieldLabelDict.Add("SanctionResult", "Sanction Result");
            Candidate_FieldLabelDict.Add("PECCheckResult", "PEC Check Result");
            Candidate_FieldLabelDict.Add("PECRemarks", "PEC Remarks");
            Candidate_FieldLabelDict.Add("TrainingBatch", "Training Batch");
            Candidate_FieldLabelDict.Add("TrainingDate", "Training Date");
            Candidate_FieldLabelDict.Add("TrainerName", "Trainer Name");
            Candidate_FieldLabelDict.Add("TrainingAttendance", "Training Attendance");
            Candidate_FieldLabelDict.Add("TrainingAttendanceRemarks", "Training Attendance Remarks");
            Candidate_FieldLabelDict.Add("ReTest", "Re Test");
            Candidate_FieldLabelDict.Add("ReTestRequirement", "Re Test Requirement");
            Candidate_FieldLabelDict.Add("TrainingResult", "Training Result");
            Candidate_FieldLabelDict.Add("OBEligible", "OBEligible");
            Candidate_FieldLabelDict.Add("DocumentCompletion", "Document Completion");
            Candidate_FieldLabelDict.Add("DocumentIncompletionRemarks", "Document Incompletion Remarks");
            Candidate_FieldLabelDict.Add("PCReceiptSubmissionDate", "PC Receipt Submission Date");
            Candidate_FieldLabelDict.Add("PCReportSubmissionDate", "PC Report Submission Date");
            Candidate_FieldLabelDict.Add("HiringManagerName", "Hiring Manager Name");
            Candidate_FieldLabelDict.Add("HiringManagerAcknowledgeDate", "Hiring Manager Acknowledge Date");
            Candidate_FieldLabelDict.Add("DelegateApproverName", "Delegate Approver Name");
            Candidate_FieldLabelDict.Add("ApprovingDate", "Approving Date");
            Candidate_FieldLabelDict.Add("OnBoarding", "OnBoarding");
            Candidate_FieldLabelDict.Add("OnBoardingRemarks", "OnBoarding Remarks");
            Candidate_FieldLabelDict.Add("CICSanctionRequestDate", "CIC Sanction RequestDate");
            Candidate_FieldLabelDict.Add("TrainingResultCC", "Training Result CC");
            Candidate_FieldLabelDict.Add("CheckChannel", "Check Channel");
        }

        #region Action
        private void btnAdd_Click(object sender, EventArgs e)
        {
            try
            {
                CandidateOffline candidateOffline = new CandidateOffline();

                frmCandidateOffline fmCandidateOffline = new frmCandidateOffline(MiscHelper.FORM_OPMODE_ADD_NEW, listCandidateOffline);
                DialogResult result = fmCandidateOffline.ShowDialog(this);

                candidateOffline = fmCandidateOffline.candidateOffline;
                listCandidateOffline = fmCandidateOffline.ListCandidateOffline;
                if (result == DialogResult.Cancel)
                {
                    LoadData();
                    RefreshCandidateCount();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnSendmail_Click(object sender, EventArgs e)
        {
            try
            {
                if (!ValidateSendmail())
                {
                    return;
                }

                if (listCandidateOffline != null && listCandidateOffline.Count > 0)
                {
                    string filename = "Candidate_" + txtBranch.Text.Trim() + "_" + txtFloor.Text.Trim() + "_" + DateTime.Now.ToString("MMddyyyy") + ".xls";
                    string fileTemp = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + filename;
                    DataTable dtData = ConvertToDataTable<CandidateOffline>(listCandidateOffline);
                    NPOIHelper.ExportCandidate(dtData, "CANDIDATE", fileTemp, Candidate_FieldLabelDict);
                    SendEMailThroughOUTLOOK(fileTemp, txtBranch.Text.Trim(), txtFloor.Text.Trim());

                    listCandidateOffline.Clear();
                    LoadData();
                    RefreshCandidateCount();
                }
                else
                {
                    MessageBox.Show("We don't have any candidates to export. Please add new candidate.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnEdit_Click(object sender, EventArgs e)
        {
            try
            {
                int selectedRowCount = dgvDataCandidateOffline.Rows.GetRowCount(DataGridViewElementStates.Selected);
                if (selectedRowCount > 0)
                {
                    CandidateOffline candidateOffline = (CandidateOffline)dgvDataCandidateOffline.SelectedRows[0].DataBoundItem;
                    List<CandidateOffline> tempList = new List<CandidateOffline>();
                    List<Candidate> temListRemain = new List<Candidate>();

                    tempList.Add(candidateOffline);
                    frmCandidateOffline fmCo = new frmCandidateOffline(MiscHelper.FORM_OPMODE_EDIT, tempList);
                    DialogResult result = fmCo.ShowDialog(this);
                    if (result == DialogResult.OK)
                    {
                        listCandidateOffline.Remove(candidateOffline);
                        candidateOffline = fmCo.candidateOffline;
                        listCandidateOffline.Add(candidateOffline);
                        LoadData();
                    }
                }
                else
                {
                    MessageBox.Show("Not candidate is selected.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void btnDelete_Click(object sender, EventArgs e)
        {
            try
            {
                int selectedRowCount = dgvDataCandidateOffline.Rows.GetRowCount(DataGridViewElementStates.Selected);
                if (selectedRowCount > 0)
                {
                    CandidateOffline candidateOffline = (CandidateOffline)dgvDataCandidateOffline.SelectedRows[0].DataBoundItem;
                    DialogResult result = MessageBox.Show("Are you sure you want to delete this candidate?", "Delete confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                       MessageBoxDefaultButton.Button2);
                    if (result == DialogResult.Yes)
                    {
                        listCandidateOffline.Remove(candidateOffline);
                        LoadData();
                        RefreshCandidateCount();
                    }
                }
                else
                {
                    MessageBox.Show("Not candidate is selected.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }

        #endregion

        private bool ValidateSendmail()
        {
            try
            {
                if (string.IsNullOrEmpty(txtBranch.Text.Trim()))
                {
                    MessageBox.Show("Branch cannot be empty.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtBranch.Focus();
                    return false;
                }
                if (string.IsNullOrEmpty(txtFloor.Text.Trim()))
                {
                    MessageBox.Show("Floor cannot be empty.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtFloor.Focus();
                    return false;
                }
                if (txtBranch.Text.Length + txtFloor.Text.Length > 250)
                {
                    MessageBox.Show("Total lenght of 'Office/Channel Add' and 'Floor' is too long!", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    if (txtBranch.Text.Length > txtFloor.Text.Length)
                    {
                        txtBranch.Focus();
                    }
                    else
                    {
                        txtFloor.Focus();
                    }
                    return false;
                }
                return true;
            }
            catch (Exception ex) { throw ex; }
        }
        private void SendEMailThroughOUTLOOK(string fileTemp, string branch, string floor)
        {
            try
            {
                // Create the Outlook application.
                Outlook.Application oApp = new Outlook.Application();

                // Create a new mail item.
                Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);

                // Set HTMLBody. 
                //add the body of the email
                oMsg.HTMLBody = "Content";

                //Add an attachment.
                String sDisplayName = "MyAttachment";
                int iPosition = (int)oMsg.Body.Length + 1;
                int iAttachType = (int)Outlook.OlAttachmentType.olByValue;

                //now attached the file             
                var oAttach = oMsg.Attachments.Add(fileTemp, iAttachType, iPosition, sDisplayName);

                if (File.Exists(fileTemp)) File.Delete(fileTemp);

                //Subject line
                oMsg.Subject = "New Candidate" + "-" + branch + "-" + floor + "-" + DateTime.Now.ToString("MMddyyyy");
                oMsg.To = "";
                oMsg.CC = "";
                oMsg.Display(true);

            }
            catch (Exception ex) { throw ex; }
        }
        private void RefreshCandidateCount()
        {
            lbInfoListData.Text = "No. of record(s) : " + (listCandidateOffline != null ? listCandidateOffline.Count.ToString() : "0");
        }

        #endregion

        #region Employment
        public void LoadDataEmploymentOffline()
        {
            //load employment offline
            EmploymentOfflineBLL employmentofflineBll = new EmploymentOfflineBLL();
            DataTable dtData = employmentofflineBll.GetEmploymentOfflines();
            dgvData.DataSource = null;
            dgvData.Columns.Clear();
            dgvData.DataSource = dtData;
            dgvData.AutoResizeColumns();

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(EmploymentOffline));
            foreach (PropertyDescriptor prop in properties)
            {
                dgvData.Columns[prop.Name].HeaderText = Employment_FieldLabelDict[prop.Name];

                string dataType = prop.PropertyType.Name;

                if (!dataType.ToUpper().Equals("STRING"))
                {
                    dgvData.Columns[prop.Name].DefaultCellStyle.Format = "dd MMM, yyyy";
                }
            }
        }

        public void BuildEmploymentOfflineLabel()
        {
            Employment_FieldLabelDict = new Dictionary<string, string>();
            Employment_FieldLabelDict.Add("ID", "ID");// show header when load data from database
            Employment_FieldLabelDict.Add("ProfileID", "Profile ID");
            Employment_FieldLabelDict.Add("CandidateCode", "Candidate Code");
            Employment_FieldLabelDict.Add("CurrentSalesCode", "Current Sales Code");
            Employment_FieldLabelDict.Add("EmployeeFullName", "Employee Full Name");
            Employment_FieldLabelDict.Add("EmployeeFullNameE", "Employee Full Name_E");
            Employment_FieldLabelDict.Add("Role", "Role");
            Employment_FieldLabelDict.Add("Level", "Level");
            Employment_FieldLabelDict.Add("Category", "Category");
            Employment_FieldLabelDict.Add("ProductCategory", "Product Category");
            Employment_FieldLabelDict.Add("Product", "Product");
            Employment_FieldLabelDict.Add("TeamName", "Team Name");
            Employment_FieldLabelDict.Add("TeamLeaderCode", "Team Leader Code");
            Employment_FieldLabelDict.Add("Channel", "Channel");
            Employment_FieldLabelDict.Add("JoiningDate", "Joining Date");
            Employment_FieldLabelDict.Add("PromotionTransferDate", "Promotion/Role Transfer Date");
            Employment_FieldLabelDict.Add("Status", "Status");
            Employment_FieldLabelDict.Add("ContractType", "Contract Type");
            Employment_FieldLabelDict.Add("ContractTerm", "Contract Term");
            Employment_FieldLabelDict.Add("ContractorName", "Contractor Name");
            Employment_FieldLabelDict.Add("ContractSignDate", "Contract Sign Date");
            Employment_FieldLabelDict.Add("ContractExpiryDate", "Contract Expiry Date");
            Employment_FieldLabelDict.Add("BatchFileID", "Batch File ID");
        }

        public void BuildChangeRequestEmploymentOfflineLabel()
        {
            ChangeRequest_Employment_FieldLabelDict = new Dictionary<string, string>();
            ChangeRequest_Employment_FieldLabelDict.Add("ProfileID", "Profile ID");// show header when load data from database
            ChangeRequest_Employment_FieldLabelDict.Add("BatchFile", "Batch File");
            ChangeRequest_Employment_FieldLabelDict.Add("FieldChange", "Field Change");
            ChangeRequest_Employment_FieldLabelDict.Add("OldValue", "Old Value");
            ChangeRequest_Employment_FieldLabelDict.Add("NewValue", "New Value");
        }
        private EmploymentOffline UnPackObjectData_Employee(DataRow drData)
        {
            employment = new EmploymentOffline();
            employment.ProfileID = drData["ProfileID"].ToString();
            employment.CandidateCode = drData["CandidateCode"].ToString();
            employment.CurrentSalesCode = drData["CurrentSalesCode"].ToString();
            employment.EmployeeFullName = drData["EmployeeFullName"].ToString();
            employment.EmployeeFullNameE = drData["EmployeeFullNameE"].ToString();
            employment.Role = drData["Role"].ToString();
            employment.Level = drData["Level"].ToString();
            employment.Category = drData["Category"].ToString();
            employment.ProductCategory = drData["ProductCategory"].ToString();
            employment.Product = drData["Product"].ToString();
            employment.TeamName = drData["TeamName"].ToString();
            employment.TeamLeaderCode = drData["TeamLeaderCode"].ToString();
            employment.Channel = drData["Channel"].ToString();
            employment.JoiningDate = Convert.ToDateTime(drData["JoiningDate"] != null ? drData["JoiningDate"] : (DateTime?)null);
            employment.PromotionTransferDate = Convert.ToDateTime(drData["PromotionTransferDate"] != null ? drData["PromotionTransferDate"] : (DateTime?)null);
            employment.Status = drData["Status"].ToString();

            employment.ContractType = drData["ContractType"].ToString();
            employment.ContractTerm = drData["ContractTerm"].ToString();
            employment.ContractorName = drData["ContractorName"].ToString();
            employment.ContractSignDate = Convert.ToDateTime(drData["ContractSignDate"] != null ? drData["ContractSignDate"] : (DateTime?)null);
            employment.ContractExpiryDate = Convert.ToDateTime(drData["ContractExpiryDate"] != null ? drData["ContractExpiryDate"] : (DateTime?)null);
            employment.BatchFileID = drData["BatchFileID"].ToString();

            return employment;
        }

        #region Action

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog ExcelDialog = new OpenFileDialog();
                ExcelDialog.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";
                ExcelDialog.InitialDirectory = lastPath;
                ExcelDialog.Title = "Select your file excel";
                if (ExcelDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    btnSave.Enabled = false;
                    txtFileName.Text = ExcelDialog.FileName;
                    txtFileName.ReadOnly = true;

                    string fileName = ExcelDialog.SafeFileName;
                    string[] checkFileName = fileName.Split('_');
                    if (checkFileName[0].ToLower().Equals("approved"))
                    {
                        DataTable dtData = NPOIHelper.ImportExceltoDt(txtFileName.Text.Trim(), 0, 1);
                        dgvData.DataSource = null;
                        dgvData.Columns.Clear();
                        dgvData.DataSource = dtData;
                        dgvData.AutoResizeColumns();

                        //btnsave
                        btnSave.Enabled = true;

                        //update info
                        this.OpMode = 2;
                    }
                    else
                    {
                        DataTable dtData = NPOIHelper.ImportExceltoDt(txtFileName.Text.Trim(), 0, 2);

                        //convert datacolumn
                        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(EmploymentOffline));
                        foreach (PropertyDescriptor prop in properties)
                        {
                            if (!prop.Name.Equals("ID"))
                            {
                                dtData.Columns[Employment_FieldLabelDict[prop.Name]].ColumnName = prop.Name;
                            }
                        }

                        dgvData.DataSource = null;
                        dgvData.Columns.Clear();
                        dgvData.DataSource = dtData;
                        dgvData.AutoResizeColumns();

                        //custome header text
                        foreach (PropertyDescriptor prop in properties)
                        {
                            if (!prop.Name.Equals("ID"))
                            {
                                dgvData.Columns[prop.Name].HeaderText = Employment_FieldLabelDict[prop.Name];
                            }
                        }

                        //btnsave
                        btnSave.Enabled = true;

                        //insert new employee
                        this.OpMode = 1;
                    }

                    var tmp = txtFileName.Text;
                    tmp = tmp.Substring(0, tmp.LastIndexOf("\\"));
                    if (lastPath != tmp)
                        lastPath = tmp;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Import file has structure invalid", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                DialogResult result = MessageBox.Show("Are you want to save ?", "Save confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                   MessageBoxDefaultButton.Button2);
                if (result == DialogResult.Yes)
                {
                    if (this.OpMode == 1)
                    {
                        listEmploymentOffline.Clear();
                        DataTable dtData = (DataTable)dgvData.DataSource;
                        foreach (DataRow dr in dtData.Rows)
                        {
                            employment = UnPackObjectData_Employee(dr);
                            listEmploymentOffline.Add(employment);
                        }

                        if (listEmploymentOffline != null && listEmploymentOffline.Count > 0)
                        {
                            EmploymentOfflineBLL employmentOfflineBll = new EmploymentOfflineBLL();
                            employmentOfflineBll.Save(listEmploymentOffline);
                        }
                        MessageBox.Show("The employees are imported successfully.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);

                        btnSave.Enabled = false;
                    }
                    else
                    {
                        DataTable dtData = (DataTable)dgvData.DataSource;
                        List<string> profileIDs = new List<string>();
                        List<string> batchfileIDs = new List<string>();

                        foreach (DataRow dr in dtData.Rows)
                        {
                            if (!string.IsNullOrEmpty(dr[0].ToString()))
                            {
                                profileIDs.Add(dr[0].ToString());
                            }
                            else
                            {
                                batchfileIDs.Add(dr[1].ToString());
                            }
                        }

                        profileIDs = profileIDs.Distinct().ToList();
                        batchfileIDs = batchfileIDs.Distinct().ToList();

                        EmploymentOfflineBLL employmentOfflineBll = new EmploymentOfflineBLL();
                        employmentOfflineBll.Update(dtData, profileIDs, batchfileIDs);
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnSearch_Click(object sender, EventArgs e)
        {
            string saleCode = txtSaleCode.Text.Trim();
            string fullName = txtFullName.Text.Trim();
            string profileID = txtProfileID.Text.Trim();
            string batchFileID = txtBatchFile.Text.Trim();

            if (string.IsNullOrEmpty(saleCode))
            {
                saleCode = null;
            }
            if (string.IsNullOrEmpty(fullName))
            {
                fullName = null;
            }
            if (string.IsNullOrEmpty(profileID))
            {
                profileID = null;
            }
            if (string.IsNullOrEmpty(batchFileID))
            {
                batchFileID = null;
            }

            try
            {
                EmploymentOfflineBLL employmentOfflineBll = new EmploymentOfflineBLL();
                DataTable dtData = employmentOfflineBll.Search(saleCode, fullName, profileID, batchFileID);

                dgvData.DataSource = null;
                dgvData.Columns.Clear();
                dgvData.DataSource = dtData;
                dgvData.AutoResizeColumns();

                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(EmploymentOffline));
                foreach (PropertyDescriptor prop in properties)
                {
                    dgvData.Columns[prop.Name].HeaderText = Employment_FieldLabelDict[prop.Name];
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void dgvData_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            try
            {
                int selectedRowCount = dgvData.Rows.GetRowCount(DataGridViewElementStates.Selected);
                if (selectedRowCount > 0)
                {
                    DataRow dr = ((DataRowView)dgvData.SelectedRows[0].DataBoundItem).Row;
                    employmentTemp = UnPackObjectData_Employee(dr);
                    LoadFieldName();
                    txtProfileIDChange.Text = employmentTemp.ProfileID;
                    txtBatchFileChange.Text = employmentTemp.BatchFileID;
                    cbField.SelectedIndex = 0;

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnUpdateEmployment_Click(object sender, EventArgs e)
        {
            try
            {
                if (!ValidateUpdateChange())
                {
                    return;
                }

                if (chbBatchFile.Checked)
                {
                    //save in datatable -> view 
                    DataRow dr = dtDataEmployeeChangeTemp.NewRow();
                    DataRow[] foundRows = dtDataEmployeeChangeTemp.Select("BatchFile= '" + txtBatchFileChange.Text + "' AND FieldChange = '" + cbField.Text + "'");
                    if (foundRows.Length > 0)
                    {
                        foundRows[0]["NewValue"] = txtNewValue.Text;
                    }
                    else
                    {
                        dr["BatchFile"] = txtBatchFileChange.Text;
                        dr["FieldChange"] = cbField.Text;
                        dr["OldValue"] = txtOldValue.Text;
                        dr["NewValue"] = txtNewValue.Text;
                        dr["FirstValue"] = txtOldValue.Text;
                        dtDataEmployeeChangeTemp.Rows.Add(dr);
                    }

                    RefreshEmploymentChangeCount();

                    MessageBox.Show("Change info saved.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                if (txtNewValue.Text != null && employmentTemp != null)
                {
                    //save in datatable -> view 
                    DataRow dr = dtDataEmployeeChangeTemp.NewRow();
                    DataRow[] foundRows = dtDataEmployeeChangeTemp.Select("ProfileID= '" + employmentTemp.ProfileID + "' AND FieldChange = '" + cbField.Text + "'");
                    if (foundRows.Length > 0)
                    {
                        foundRows[0]["NewValue"] = txtNewValue.Text;
                    }
                    else
                    {
                        dr["ProfileID"] = employmentTemp.ProfileID;
                        dr["FieldChange"] = cbField.Text;
                        dr["OldValue"] = txtOldValue.Text;
                        dr["NewValue"] = txtNewValue.Text;
                        dr["FirstValue"] = txtOldValue.Text;
                        dtDataEmployeeChangeTemp.Rows.Add(dr);
                    }

                    RefreshEmploymentChangeCount();

                    MessageBox.Show("Change info saved.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show("Nothing to change.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnViewChange_Click(object sender, EventArgs e)
        {
            try
            {
                if (dtDataEmployeeChangeTemp != null && dtDataEmployeeChangeTemp.Rows.Count > 0)
                {
                    frmEmployeeOffline frmEmploymentChange = new frmEmployeeOffline(ref dtDataEmployeeChangeTemp);
                    DialogResult result = frmEmploymentChange.ShowDialog(this);
                    if (result == DialogResult.OK || result == DialogResult.None || result == DialogResult.Cancel)
                    {
                        dtDataEmployeeChangeTemp = frmEmploymentChange.dtEmploymentChange;

                        RefreshEmploymentChangeCount();
                    }
                }
                else
                {
                    MessageBox.Show("Nothing change to view.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void btnExportChange_Click(object sender, EventArgs e)
        {
            try
            {
                if (dtDataEmployeeChangeTemp != null && dtDataEmployeeChangeTemp.Rows.Count > 0)
                {
                    dtDataEmployeeChangeTemp.Columns.Remove("FirstValue");

                    string filename = "Change_Request_" + txtBranch.Text.Trim() + "_" + txtFloor.Text.Trim() + "_" + DateTime.Now.ToString("MMddyyyy") + ".xls";
                    string fileTemp = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + filename;
                    NPOIHelper.ExportDTtoExcel(dtDataEmployeeChangeTemp, "Change", fileTemp, ChangeRequest_Employment_FieldLabelDict);
                    SendEMailThroughOUTLOOK(fileTemp, txtBranch.Text.Trim(), txtFloor.Text.Trim());

                    dtDataEmployeeChangeTemp.Rows.Clear();

                    RefreshEmploymentChangeCount();

                    dtDataEmployeeChangeTemp.Columns.Add("FirstValue");
                }
                else
                {
                    MessageBox.Show("We don't have any change to export. Please add new change.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        private void cbField_SelectedIndexChanged(object sender, EventArgs e)
        {
            txtNewValue.Text = "";
            txtNewValue.WatermarkText = "";
            if (employmentTemp != null && cbField.SelectedItem != null)
            {
                string dataType = employmentTemp.GetType().GetProperty(((System.Collections.Generic.KeyValuePair<string, string>)(cbField.SelectedItem)).Key).PropertyType.Name;
                if (!dataType.ToUpper().Equals("STRING"))
                {
                    txtOldValue.Text = ((DateTime)employmentTemp.GetType().GetProperty(((System.Collections.Generic.KeyValuePair<string, string>)(cbField.SelectedItem)).Key).GetValue(employmentTemp, null)).ToShortDateString();
                    txtNewValue.WatermarkText = "dd/mm/yyyy";
                }
                else
                {
                    txtOldValue.Text = employmentTemp.GetType().GetProperty(((System.Collections.Generic.KeyValuePair<string, string>)(cbField.SelectedItem)).Key).GetValue(employmentTemp, null).ToString();
                }
            }
        }

        #endregion


        /// <summary>
        /// Load data form Masterdata table base on Master ID
        /// </summary>
        /// <param name="masterId">Use MasterData.MASTERID</param>
        /// <returns>Return an Array of Key value in Master datatable</returns>
        public string[] LoadMasterData(string masterId)
        {
            string masterId_original = masterId.Replace(" ", string.Empty);
            List<string> getList = new List<string>();
            new MasterDataBLL().GetById(masterId_original).Rows.OfType<DataRow>().ToList<DataRow>().ForEach(r => getList.Add(r["KeyValue"].ToString()));
            string[] array = getList.ToArray<string>();
            return array;
        }

        /// <summary>
        /// Load autocompleted value for textbox newValue
        /// </summary>
        /// <param name="source">Array of Master data</param>
        public void AutoCompleteNewValue(string[] source)
        {
            txtNewValue.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            txtNewValue.AutoCompleteSource = AutoCompleteSource.CustomSource;
            var sourceCollection = new AutoCompleteStringCollection();
            sourceCollection.AddRange(source);
            txtNewValue.AutoCompleteCustomSource = sourceCollection;
        }

        private void LoadFieldName()
        {
            //cbField.Items.Clear();
            cbField.DataSource = null;
            if (employmentTemp != null)
            {
                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(EmploymentOffline));
                var dataSource = new BindingList<KeyValuePair<string, string>>();
                foreach (PropertyDescriptor prop in properties)
                {
                    if (!prop.Name.Equals("ID") && !prop.Name.Equals("ProfileID") && !prop.Name.Equals("BatchFileID") && !prop.Name.Equals("ContractType") && !prop.Name.Equals("ContractTerm") && !prop.Name.Equals("ContractorName") && !prop.Name.Equals("ContractExpiryDate"))
                    {
                        dataSource.Add(new KeyValuePair<string, string>(prop.Name, Employment_FieldLabelDict[prop.Name]));
                        //cbField.Items.Add(Employment_FieldLabelDict[prop.Name]);
                    }
                }
                cbField.DataSource = dataSource;
                cbField.ValueMember = "Key";
                cbField.DisplayMember = "Value";
            }
        }
        private void RefreshEmploymentChangeCount()
        {
            lbInfoEmployment.Text = "Number of Change(s) :" + (dtDataEmployeeChangeTemp != null ? dtDataEmployeeChangeTemp.Rows.Count.ToString() : "0"); 
        }
        private bool ValidateUpdateChange()
        {
            try
            {
                //Check empty
                if (cbField.Text.Equals(""))
                {
                    MessageBox.Show("Field cannot be empty.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }

                if (string.IsNullOrEmpty(txtOldValue.Text))
                {
                    MessageBox.Show("Old Value cannot be empty.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtOldValue.Focus();
                    return false;
                }
                if (string.IsNullOrEmpty(txtNewValue.Text))
                {
                    MessageBox.Show("New Value cannot be empty.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtNewValue.Focus();
                    return false;
                }

                //Check Channel, TeamName, Role, Status, Level 
                string[] fieldbeCheckExistence = new string[] { "Channel", "Team Name", "Role", "Status", "Level" };
                if (fieldbeCheckExistence.Contains(cbField.Text))
                {
                    if (!LoadMasterData(cbField.Text).Contains<string>(txtNewValue.Text))
                    {
                        MessageBox.Show("Please input again. This value is not satisfied", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        txtNewValue.Focus();
                        return false;
                    }
                }

                //Check JoiningDate, PromotionTransferDate, DateOfBirth, IDIssuedDate, ContractSignDate, ContractExpiryDate
                string[] fieldbeCheckDate = new string[] { "Joining Date", "Promotion/Role Transfer Date", "Contract Sign Date", "Contract Expiry Date" };
                if (fieldbeCheckDate.Contains(cbField.Text))
                {
                    Regex rgx = new Regex(@"^([0]?[1-9]|[1|2][0-9]|[3][0|1])[./-]([0]?[1-9]|[1][0-2])[./-]([0-9]{4}|[0-9]{2})$");
                    if (!rgx.IsMatch(txtNewValue.Text))
                    {
                        MessageBox.Show("Please input right date format: dd/mm/yyyy", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        txtNewValue.Focus();
                        return false;
                    }
                }
                return true;
            }
            catch (Exception ex) { throw ex; }
        }
        #endregion

        #region Email
        private void btnUpdateMail_Click(object sender, EventArgs e)
        {
            try
            {
                if (!ValidateSendmail())
                {
                    return;
                }
                if (mailConfig == null)
                {
                    mailConfig = new MailConfig();
                }

                mailConfig.Branch = txtBranch.Text;
                mailConfig.Floor = txtFloor.Text;
                mailConfig.CreatedDate = MiscHelper.DateTimeToShort(DateTime.Now);
                mailConfig.LastUpdate = MiscHelper.DateTimeToShort(DateTime.Now);

                MailConfigBLL mailConfigBll = new MailConfigBLL();
                mailConfigBll.Save(mailConfig);
                MessageBox.Show("Updated successfully");
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }
        #endregion

        public DataTable ConvertToDataTable<T>(List<T> data)
        {
            try
            {
                PropertyDescriptorCollection properties =
                   TypeDescriptor.GetProperties(typeof(T));
                DataTable table = new DataTable();
                foreach (PropertyDescriptor prop in properties)
                    table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
                foreach (T item in data)
                {
                    DataRow row = table.NewRow();
                    foreach (PropertyDescriptor prop in properties)
                        row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                    table.Rows.Add(row);
                }
                return table;
            }
            catch (Exception ex) { throw ex; }

        }
        private void frmCandidateMaster_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                EmploymentOfflineBLL eoBLL = new EmploymentOfflineBLL();
                eoBLL.SaveChangeTemp(dtDataEmployeeChangeTemp);
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }

        private void frmCandidateMaster_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                DialogResult result = MessageBox.Show(Constant.SYS_MSG_EXIT_APP, "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                        MessageBoxDefaultButton.Button2);
                if (result == DialogResult.No)
                {
                    e.Cancel = true;
                }
            }
        }

        private void txtNewValue_Click(object sender, EventArgs e)
        {
            string[] autoCompletedfield = new string[] { "Channel", "Team Name", "Role", "Level", "Status" };
            if (autoCompletedfield.Contains(cbField.Text))
            {
                AutoCompleteNewValue(LoadMasterData(cbField.Text.ToUpper()));
            }
        }

        private void lbInfoEmployment_MouseHover(object sender, EventArgs e)
        {
            RefreshEmploymentChangeCount();
        }


       
    }
}
